<?php

namespace app\model;

use Carbon\Carbon;
use think\facade\Db;
use think\Model;

abstract class BaseModel extends Model
{
    protected $field;
    protected $isConvert = false;

    protected $data = [];
    protected $relationId = 0;

    public function getField()
    {
        $class = new \ReflectionClass(static::class);
        $model = $class->newInstance();
        return $model->getFields();
    }

    public function getDateField()
    {
       return [
           'created_at','updated_at','cancelled_at','closed_at',
           'processed_at',''
       ];
    }

    public function setIsConvert(bool $isConvert)
    {
         $this->isConvert = $isConvert;
         return $this;
    }

    public function fill(array $data)
    {
        $this->setDatas($data)->formatData();
        return $this;
    }

    public function saveData()
    {
        return $this->insertGetId($this->getDatas());
    }

    public function setDatas(array $data)
    {
        $this->data = $data;
        return $this;
    }

    public function getDatas()
    {
        return $this->data;
    }

    public function setRelationId($relationId)
    {
        $this->relationId = $relationId;
        return $this;
    }

    public function getRelationId()
    {
        return $this->relationId;
    }

    protected function formatData()
    {
        //$fields = $this->getField();
        $fields = static ::getFields();
        foreach ($this->data as $key => &$item){
            if(is_numeric($key)){
                foreach ($item as $kk => &$vv){
                    if(in_array($kk,$this->getDateField())){
                        $item[$kk] = Carbon::parse($vv)->timestamp;
                    }
                    if(is_bool($vv)) $item[$kk] = $item[$kk] ? 1 : 0;
                    if(!in_array($kk,$fields)) unset($item[$kk]);

                }

            }else{
                if(in_array($key,$this->getDateField())){
                    $this->data[$key] = Carbon::parse($item)->timestamp;
                }
                if(is_bool($item)) $this->data[$key] = $item ? 1 : 0;
                if(!in_array($key,$fields)) unset($this->data[$key]);

            }

        }
    }

    protected function getFields()
    {
        return $this->field;
    }

    /**
     * 批量更新数据（支持JSON字段）
     * @param array $data 更新数据
     * @param string $primaryKey 主键字段名
     * @return int 影响的行数
     */
    public function batchUpdate(array $data, string $primaryKey = 'id'): int
    {
        if (empty($data)) {
            return 0;
        }

        $table = $this->getTable();
        $sql = $this->buildBatchUpdateSql($table, $data, $primaryKey);

        return Db::execute($sql);
    }

    /**
     * 构建批量更新SQL
     */
    private function buildBatchUpdateSql(string $table, array $data, string $primaryKey): string
    {
        $cases = [];
        $ids = [];

        // 获取所有字段
        $firstRow = $data[0];
        $fields = array_keys($firstRow);
        $fields = array_filter($fields, function($field) use ($primaryKey) {
            return $field !== $primaryKey;
        });

        foreach ($fields as $field) {
            $caseSql = "`{$field}` = CASE `{$primaryKey}` ";

            foreach ($data as $item) {
                $id = $item[$primaryKey];
                $value = $item[$field] ?? null;

                // 处理JSON字段
                if ($this->isJsonField($value)) {
                    $value = $this->formatJsonForDb($value);
                } else {
                    $value = $this->escapeValue($value);
                }

                $caseSql .= "WHEN {$id} THEN {$value} ";
                $ids[$id] = true;
            }

            $caseSql .= "ELSE `{$field}` END";
            $cases[] = $caseSql;
        }

        $idList = implode(',', array_keys($ids));
        $setClause = implode(', ', $cases);

        return "UPDATE `{$table}` SET {$setClause} WHERE `{$primaryKey}` IN ({$idList})";
    }

    /**
     * 判断是否为JSON字段
     */
    private function isJsonField($value): bool
    {
        // 可以根据表结构判断，这里简单处理
        if (is_array($value) || is_object($value)) {
            return true;
        }

        return false;
    }

    /**
     * 格式化JSON数据用于数据库
     */
    private function formatJsonForDb($data): string
    {
        if (is_array($data) || is_object($data)) {
            $json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            return "'" . addslashes($json) . "'";
        }

        return "'" . addslashes($data) . "'";
    }

    /**
     * 转义值
     */
    private function escapeValue($value): string
    {
        if (is_null($value)) {
            return 'NULL';
        }

        if (is_bool($value)) {
            return $value ? '1' : '0';
        }

        if (is_numeric($value)) {
            return $value;
        }

        return "'" . addslashes($value) . "'";
    }


}